package com.dongbao.core.rules.java;

import com.dongbao.core.base.CodeRulesCommonBase;
import com.dongbao.core.rules.CodeRulesBase;
import com.dongbao.entity.AwardedInfo;
import com.intellij.lang.jvm.JvmParameter;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.*;
import com.intellij.psi.impl.source.PsiClassImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 *  巧用建造者模式进行对象组合创建（不同的组合生成出所谓的套餐)
 *  remark:在构造方法内全是赋值操作的才会提示,如果存在其他的操作代码或者方法调用的则不会提示
 * */
public class StructurePatternRules extends CodeRulesCommonBase implements CodeRulesBase {

    private final Integer MAX_PARAM = 4;

    public StructurePatternRules(VirtualFile afterFile,PsiFile psiFile,Project project) {
        super(afterFile,psiFile,project);
        this.code = "A005";
        this.level = "A";
    }

    /**
     * 执行规则判断
     * */
    @Override
    public void run(List<AwardedInfo> deduction) {
        /* 执行分析当前class是否负责当前规则 */
        PsiAnnotation[] annotations = psiClassImpls.get(0).getModifierList().getAnnotations();
        for(PsiClassImpl psiClass:psiClassImpls){
            /* 获取所有方法 */
            PsiMethod[] allMethods = psiClass.getMethods();
            if(allMethods == null){
                continue;
            }
            /* 查找方法名跟类名相同的方法 */
            List<PsiMethod> constructor = Arrays.asList(allMethods).stream().filter(method -> {
                return method.getName().equals(psiClass.getName());
            }).collect(Collectors.toList());
            if(constructor.isEmpty()){
                /* 未找到跟类名相同的方法 */
                continue;
            }
            /* 检查所有构造方法中的参数个数 */
            for(PsiMethod method:constructor){
                /* 方法中的参数集合 */
                JvmParameter[] parameters = method.getParameters();
                /* 判断方法内部的方式是否是直接将参数赋值给了class类中属性对象 */
                if(parameters.length > MAX_PARAM && method.getBody() != null){
                    /* 获取方法内的内容 */
                    PsiElement[] children = method.getBody().getChildren();
                    /* 判断方法内是否都是赋值的操作 */
                    List<PsiElement> psiElement = Arrays.asList(children).stream().filter(methodRow -> {
                        if(methodRow instanceof PsiJavaToken){
                            return false;
                        }
                        if(methodRow instanceof PsiWhiteSpace){
                            return false;
                        }
                        /* 判断是否是赋值的代码操作 */
                        if(methodRow instanceof PsiExpressionStatement && ((PsiExpressionStatement)methodRow).getFirstChild() instanceof PsiAssignmentExpression){
                            return false;
                        }
                        return true;
                    }).collect(Collectors.toList());
                    if(psiElement.isEmpty()){

                        /* 获取错误代码行位置 */
                        Document document = PsiDocumentManager.getInstance(psiClass.getProject()).getDocument(psiClass.getContainingFile());
                        int lineNumber = document.getLineNumber(method.getTextOffset());

                        /* 判断方法内的代码是否都是赋值的操作 */
                        packDeduction(
                                deduction,
                                psiClass.getName(),
                                psiPackageStatements.get(0).getPackageName(),
                                method.getName(),
                                "巧用建造者模式进行对象组合创建（不同的组合生成出所谓的套餐),对于构造参数过多的类推荐使用@Builder,",lineNumber,lineNumber);
                    }
                }
            }
        }
    }

    @Override
    public String describe() {
        return "设计模式与解耦";
    }


//    public class User {
//        private String name;
//        private String password;
//        private String address;
//        private String phone;
//        private String remark;
//        public User(String name, String password, String address, String phone, String remark) {
//            this.name = name;
//            this.password = password;
//            this.address = address;
//            this.phone = phone;
//            this.remark = remark;
//            除了赋值操作外还有其他代码的则会进行提示
//            System.out.println("666");
//        }
//    }


}
